package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author GQS @Date 2024/10/13/19:31 @Description
 */
@Service
@Slf4j
public class CartServiceImpl implements ICartService {
  @Autowired private RedisTemplate redisTemplate;

  @Autowired private RemoteProductService remoteProductService;

  private String getCartKey(Long userId) {
    // 定义key user:userId:cart
    return "user:cart:" + userId;
  }

  @Override
  public void addToCart(Long skuId, Integer skuNum) {
    // 获取当前登录用户的id
    Long userId = SecurityUtils.getUserId();
    // 构建"用户"购物车的hash结构大key user::cart:userId
    String cartKey = getCartKey(userId);

    // 2.创建hash结构绑定操作对象cartKey(方便对hash进行操作)
    BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
    // 3.判断当前商品是否已经存在于购物车中
    // 如果包含:数量进行累加(某件商品数量上限99)
    // 不包含:新增购物车商品
    // 小key 为skuId
    String hashKey = skuId.toString();
    Integer threshold = 99;
    //
    if (hashOps.hasKey(hashKey)) {
      // 4.1 说明该商品在购物车已经存在 对数量进行累加 不能超过上限99
      CartInfo cartInfo = hashOps.get(hashKey);
      int totalCount = cartInfo.getSkuNum() + skuNum;
      // 如果某件sku数量超过99, 则数量设置为99
      cartInfo.setSkuNum(totalCount > threshold ? threshold : totalCount);
      hashOps.put(hashKey, cartInfo);
    } else {
      // 4.2.1 判断购物车商品种类(不同sku)总数大于50件
      Long count = hashOps.size();
      // 如果购物车中没有该sku,添加前要判断添加后的商品种类数量是否超过50件
      if (++count > 50) {
        throw new ServiceException("商品种类数量超过上限！");
      }
      // 4.2.2 说明购物车没有该商品, 构建购物车对象,存入redis
      CartInfo cartInfo = new CartInfo();
      cartInfo.setUserId(userId);
      cartInfo.setSkuNum(skuNum > threshold ? threshold : skuNum);
      cartInfo.setUpdateTime(new Date());
      cartInfo.setCreateTime(new Date());

      // 4.2.3 远程调用商品服务获取商品sku基本信息
      R<ProductSku> productSkuResult =
          remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
      if (R.FAIL == productSkuResult.getCode()) {
        throw new ServiceException(productSkuResult.getMsg());
      }
      ProductSku productSku = productSkuResult.getData();
      cartInfo.setSkuId(skuId);
      cartInfo.setSkuName(productSku.getSkuName());
      cartInfo.setThumbImg(productSku.getThumbImg());

      // 4.2.4 远程调用商品服务获取商品实时价格
      R<SkuPrice> skuPriceResult = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
      if (R.FAIL == skuPriceResult.getCode()) {
        throw new ServiceException(skuPriceResult.getMsg());
      }
      SkuPrice skuPrice = skuPriceResult.getData();
      // 放入购物车时的价格
      cartInfo.setCartPrice(skuPrice.getSalePrice());
      // 实时价格
      cartInfo.setSkuPrice(skuPrice.getSalePrice());

      // 4.3 将购物车商品存入Redis
      hashOps.put(hashKey, cartInfo);
    }
  }

  @Override
  public List<CartInfo> getCartList() {
    // 获取当前登录用户的id
    Long userId = SecurityContextHolder.getUserId();
    String cartKey = getCartKey(userId);
    // 获取数据
    List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
    // 判断cartInfoList是否为空
    if (CollectionUtils.isEmpty(cartInfoList)) {
      throw new ServiceException("购物车为空！");
    }
    // 对购物车信息列表按照创建时间进行降序排序
    List<CartInfo> sortedCartInfoList =
        cartInfoList.stream()
            .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()))
            .toList();

    // 获取skuId列表
    List<Long> skuIdList = sortedCartInfoList.stream().map(CartInfo::getSkuId).toList();
    // 查询商品的实时价格
    R<List<SkuPrice>> skuPriceListResult =
        remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
    if (R.FAIL == skuPriceListResult.getCode()) {
      throw new ServiceException(skuPriceListResult.getMsg());
    }
    // 封装skuId与实时价格到一个Map<Long, BigDecimal>
    Map<Long, BigDecimal> skuIdToPriceMap =
        skuPriceListResult.getData().stream()
            .collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
    // 封装实时价格
    sortedCartInfoList.forEach(
        cartInfo -> cartInfo.setSkuPrice(skuIdToPriceMap.get(cartInfo.getSkuId())));
    return sortedCartInfoList;
  }

  @Override
  public void deleteCart(Long skuId) {
    // 获取当前登录用户的Id
    Long userId = SecurityContextHolder.getUserId();
    String cartKey = getCartKey(userId);
    // 获取缓存对象
    BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);
    hashOps.delete(skuId.toString());
  }

  @Override
  public void checkCart(Long skuId, Integer isChecked) {
    // 获取当前登录用户的Id
    Long userId = SecurityContextHolder.getUserId();
    // 修改缓存
    String cartKey = getCartKey(userId);
    BoundHashOperations<String, String, CartInfo> hashOperations =
        redisTemplate.boundHashOps(cartKey);
    // 先获取用户选择的商品
    if (hashOperations.hasKey(skuId.toString())) {
      CartInfo cartInfoUpd = hashOperations.get(skuId.toString());
      // cartInfoUpd 写入缓存
      cartInfoUpd.setIsChecked(isChecked);
      // 更新缓存
      hashOperations.put(skuId.toString(), cartInfoUpd);
    }
  }

  @Override
  public void allCheckCart(Integer isChecked) {
    // 获取当前登录用户的Id
    Long userId = SecurityContextHolder.getUserId();
    // 根据userId 获取购物车key
    String cartKey = getCartKey(userId);
    // 获取hash对象
    // 获取Redis模板的操作对象，用于操作Hash类型的键值对
    BoundHashOperations<String, String, CartInfo> hashOperations =
        redisTemplate.boundHashOps(cartKey);

    // 从Redis中获取购物车信息列表
    List<CartInfo> cartInfoList = hashOperations.values();

    // 遍历购物车信息列表，更新每个商品的选中状态
    cartInfoList.forEach(
        cartInfo -> {
          // 根据SKU ID获取购物车商品信息
          CartInfo cartInfoUpd = hashOperations.get(cartInfo.getSkuId().toString());
          // 设置商品的选中状态
          cartInfoUpd.setIsChecked(isChecked);
          // 更新Redis中商品的选中状态
          hashOperations.put(cartInfo.getSkuId().toString(), cartInfoUpd);
        }
    );


  }

  @Override
  public void clearCart() {
    // 获取当前登录用户的Id
    Long userId = SecurityContextHolder.getUserId();
    // 删除Redis中的购物车信息
    String cartKey = getCartKey(userId);
    redisTemplate.delete(cartKey);

  }

  @Override
  public List<CartInfo> getCartCheckedList(Long userId) {
    ArrayList<CartInfo> checkedCartInfoList = new ArrayList<>();
    // 根据用户Id获取购物车的key
    String cartKey = this.getCartKey(userId);
    // 根据购物车key获取购物车信息缓存数据
    List<CartInfo> cartInfoCacheList = redisTemplate.opsForHash().values(cartKey);
    // 判断购物车信息是否为空
    if (!CollectionUtils.isEmpty(cartInfoCacheList)){
      // 不为空则遍历购物车信息列表 将已选中的商品添加到集合中
      cartInfoCacheList.forEach(cartInfo -> {
        // 判断购物车信息是否被选中
        if (cartInfo.getIsChecked() == 1){
          checkedCartInfoList.add(cartInfo);
        }
      });
    }
    return checkedCartInfoList;
  }

  @Override
  public Boolean updateCartPrice(Long userId) {
    // 获取当前用户的购物车key
    String cartKey = this.getCartKey(userId);
    // 获取redis中当前用户的购物车数据
    BoundHashOperations hashOperations = redisTemplate.boundHashOps(cartKey);
    List<CartInfo> cartInfoCacheList = hashOperations.values();
    // List<CartInfo> cartInfoCacheList = redisTemplate.opsForHash().values(cartKey);
    // 如果购物车数据不为空
    if (CollectionUtils.isEmpty(cartInfoCacheList)){
      for (CartInfo cartInfo : cartInfoCacheList) {
        // 更新购物车中被选中的商品的价格
        if (cartInfo.getIsChecked() == 1){
          SkuPrice skuPrice = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER).getData();
          cartInfo.setSkuPrice(skuPrice.getSalePrice());
          cartInfo.setCartPrice(skuPrice.getSalePrice());
          // redisTemplate.opsForHash().put(cartKey, cartInfo.getSkuId().toString(), cartInfo);
          hashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
        }
      }
    }
    return true;
  }

  @Override
  public Boolean deleteCartCheckedList(Long userId) {
    // 获取当前用户的购物车key
    String cartKey = this.getCartKey(userId);
    // 获取redis中当前用户的购物车数据
    BoundHashOperations hashOperations = redisTemplate.boundHashOps(cartKey);
    List<CartInfo> cartInfoCacheList = hashOperations.values();
    if (!CollectionUtils.isEmpty(cartInfoCacheList)){
      for (CartInfo cartInfo : cartInfoCacheList) {
        // 删除用户购物车列表中状态为被选中的商品
        if (cartInfo.getIsChecked() == 1){
          hashOperations.delete(cartInfo.getSkuId().toString());
        }
      }
    }
    return true;
  }
}
